#include "ws2812.h"

static GPIO_TypeDef* WS2812_DatPort;
static uint16_t WS2812_DatPin;
static void(* WS2812_MidDelay)();
static void(* WS2812_LongDelay)();

static inline void WS2812_Send_High(){
    HAL_GPIO_WritePin(WS2812_DatPort, WS2812_DatPin, GPIO_PIN_SET);
    WS2812_LongDelay();
    HAL_GPIO_WritePin(WS2812_DatPort, WS2812_DatPin, GPIO_PIN_RESET);
    WS2812_LongDelay();
}

static inline void WS2812_Send_Low(){
    HAL_GPIO_WritePin(WS2812_DatPort, WS2812_DatPin, GPIO_PIN_SET);
    WS2812_MidDelay();
    HAL_GPIO_WritePin(WS2812_DatPort, WS2812_DatPin, GPIO_PIN_RESET);
    WS2812_LongDelay();
}

void WS2812_Init(GPIO_TypeDef *gpioTypeDef, uint16_t gpioPin, void(*Delay300ns)(), void(*Delay600ns)()) {
    WS2812_DatPort = gpioTypeDef;
    WS2812_DatPin = gpioPin;
    WS2812_MidDelay = Delay300ns;
    WS2812_LongDelay = Delay600ns;

}

void WS2812_Reset() {
    HAL_GPIO_WritePin(WS2812_DatPort, WS2812_DatPin, GPIO_PIN_RESET);
    HAL_Delay(1);
}

void WS2812_SendRGB(uint8_t r, uint8_t g, uint8_t b) {
    uint32_t dat = g << 16 | r << 8 | b;
    for (uint8_t i = 0; i < 24; i++){
        if (dat & (0x01 << (23 - i))){
            WS2812_Send_High();
        } else {
            WS2812_Send_Low();
        }
    }
}

void WS2812_CloseAll(uint16_t light_num) {
    WS2812_Reset();
    for (int i = 0; i < light_num; ++i) {
        WS2812_SendRGB(0, 0, 0);
    }
}

void WS2812_SendMultiRGB(uint32_t *rgbColor, uint16_t count) {
    WS2812_Reset();
    for (int i = 0; i < count; ++i) {
        WS2812_SendRGB(rgbColor[i] >> 16, rgbColor[i] >> 8, rgbColor[i]);
    }
}

void WS2812_SendOneColor(uint8_t r, uint8_t g, uint8_t b, uint16_t count) {
    WS2812_Reset();
    for (int i = 0; i < count; ++i) {
        WS2812_SendRGB(r, g, b);
    }
}

